import { nextTick, customRef, type Ref } from "vue";
import type { DomType } from "./types";
import { emitter } from "@/utils/mitt";
import { useRouterStoreHook } from "@/store/modules/router";
import { totalViceMenus } from "@/router/viceMenusConstant";
import { PxLoading } from "px-ui";
import { loadingTimeout } from "@/utils/http/constant";
import { PxMessageBox } from "px-ui";

/**
 * @description: 计算DOM元素的高度
 * @param {*} dom
 * @param {*} clientBottom 元素距离可视窗口最底部的距离，需要自己调试
 * @param {*} defaultNum 默认值
 * @return {*}
 */
export async function useCalcDomHeight(dom: DomType, clientBottom = 0, defaultNum = 100) {
  await nextTick();
  if (!dom?.getBoundingClientRect) return defaultNum;
  const innerHeight = window.innerHeight;
  const clinetTop = dom?.getBoundingClientRect()?.top;
  if (innerHeight && clinetTop && innerHeight > clinetTop + clientBottom) {
    return innerHeight - clinetTop - clientBottom;
  } else {
    return defaultNum;
  }
}

/**
 * @description: 更新DOM元素的高度
 * @param {*} tableHeight 需要被更新的高度变量（ref）
 * @param {*} dom
 * @param {*} clientBottom 元素距离可视窗口最底部的距离，需要自己调试
 * @param {*} defaultNum 默认值
 * @return {*}
 */
export async function useUpdateDomHeight(tableHeight: Ref, dom: Ref, clientBottom = 0, defaultNum = 100) {
  await nextTick();
  if (!dom.value) return;
  useCancelUpdateDomHeight();
  const updateHeightValue = async () => {
    tableHeight.value = await useCalcDomHeight(dom.value, clientBottom, defaultNum);
  };
  await updateHeightValue();
  window.addEventListener("resize", updateHeightValue, true);
  emitter.on("tagViewsChange", async () => {
    await updateHeightValue();
  });
  return updateHeightValue;
}

/**
 * @description: 取消更新高度
 * @return {*}
 */
export function useCancelUpdateDomHeight() {
  window.onresize = null;
  emitter.off("tagViewsChange", () => null);
}

/**
 * @description: 更新副路由
 * @param {ToRouteType} route  当前路由
 * @return {*}
 */
export async function useUpdateViceMenu(route: ToRouteType) {
  await nextTick();
  const routeStore = useRouterStoreHook();
  routeStore.RESET_CURRENT_VICE_MENUS();
  if (route?.meta?.viceMenu?.menus?.length) {
    let ar = route?.meta?.viceMenu?.menus?.map(item => totalViceMenus.find(ite => ite.menu === item));
    ar = ar
      ?.filter(item => item)
      ?.map((item, index) => {
        item["isActive"] = index === 0;
        return item;
      });
    routeStore.SET_SHOW_VICE_MENUS(!route?.meta?.viceMenu?.isNotImmediate);
    routeStore.SET_CURRENT_VICE_MENUS(ar);
    routeStore.SET_ACTIVE_VICE_MENU(ar[0].menu);
  } else {
    routeStore.SET_CURRENT_VICE_MENUS();
    routeStore.RESET_ACTIVE_VICE_MENU();
  }
  await nextTick();
  emitter.emit("viceMenuChange", routeStore.activeViceMenu);
}

/**
 * @description: 判断当前页面是否需要底部按钮操作栏
 * @return {*}
 */
export async function useUpdateIsNeedBottomFooter() {
  await nextTick();
  const routeStore = useRouterStoreHook();
  routeStore.SET_BOTTOM_FOOTER_HEIGHT(0);
  routeStore.SET_LEFT_WIDTH(0);
}

/**
 * @description:  开启loading
 * @param {string} target  同 px-loading option target
 * @return {*}
 */
export function useInitLoading(target: string | HTMLElement, dark: boolean = false) {
  const options = {
    target,
    fullscreen: false,
    background: dark ? "rgba(0, 30, 59, 0.8)" : undefined,
    text: ""
  };
  return PxLoading.service(options);
}

/**
 * @description:  定义 响应式 防抖 数据
 * @param {T} value
 * @param {number} delay
 * @param {function} cb
 * @return {*}
 */
export function useDebouncedRef<T>(value: T, delay: number = 1500, cb?: (v: T) => null) {
  let timer: any = null;
  return customRef((track, trigger) => {
    return {
      get() {
        track();
        return value;
      },
      set(newValue: T) {
        clearTimeout(timer);
        timer = setTimeout(() => {
          value = newValue;
          cb && cb(newValue);
          trigger();
        }, delay);
      }
    };
  });
}

/**
 * @description:  定义 响应式 节流 数据
 * @param {T} value
 * @param {number} delay
 * @param {Function} cb
 * @return {*}
 */
export function useThrottleRef<T>(value: T, delay: number = 1500, cb?: (v: T) => null) {
  let timer: any = null;
  let flag: boolean = false;
  return customRef((track, trigger) => {
    return {
      get() {
        track();
        return value;
      },
      set(newValue: T) {
        if (flag) return;
        clearTimeout(timer);
        flag = true;
        value = newValue;
        cb && cb(newValue);
        trigger();
        timer = setTimeout(() => {
          flag = false;
        }, delay);
      }
    };
  });
}

/**
 * @description:  开启loading(自当关闭)
 * @param {Ref} v
 * @param {number} timeout
 * @return {*}
 */
export function useStartLoading(v: Ref, timeout: number = loadingTimeout) {
  v.value = true;
  useCancelLoading(v, timeout);
}

/**
 * @description:  延时取消loading
 * @param {Ref} v
 * @param {number} timeout
 * @return {*}
 */
export function useCancelLoading(v: Ref, timeout: number = loadingTimeout) {
  setTimeout(() => {
    v.value = false;
  }, timeout);
}

/**
 * @description:  确认弹框
 * @param {*} type  delete
 * @param {string} message
 * @param {function} cb  成功的回调
 * @param {function} cb2  失败的回调
 * @return {*}
 */
export function useMessageBox(type?: "delete", message?: string, cb?: () => any, cb2?: () => any) {
  let msgType: "success" | "info" | "warning" | "error" = "warning";
  let confirmButtonText = "确定";
  let cancelButtonText = "取消";
  let cancelButtonClass = "use-message-box-cancel-btn";
  let confirmButtonClass = "use-message-box-confirm-btn";
  switch (type) {
    case "delete":
      confirmButtonText = "删除";
      msgType = "warning";
      confirmButtonClass = "use-message-box-confirm-delete-btn";
      break;
    default:
      msgType = "warning";
      break;
  }
  PxMessageBox.confirm(message, "提示", {
    confirmButtonText,
    cancelButtonText,
    cancelButtonClass,
    confirmButtonClass,
    type: msgType
  })
    .then(() => {
      cb && cb();
    })
    .catch(() => {
      cb2 && cb2();
    });
}

/**
 * @description:  获取静态资源链接
 * @param {string} path       资源路径
 * @param {string} baseUrl    资源baseUrl
 * @return {*}
 */
export const useGetStaticUrl = (path: string, baseUrl?: string): string => {
  if (!baseUrl) {
    baseUrl = import.meta.env.VITE_SERVE_API_STATIC_URL;
  }
  if (!baseUrl) {
    baseUrl = window.location.host;
  }
  return new URL(path, baseUrl).href;
};

export const useDownloadEcharts = (echartsRefValue: any, name: string = "导出图片"): void => {
  const img = new Image();
  img.src = echartsRefValue?.getDataURL({
    type: "png",
    pixelRatio: 1,
    backgroundColor: "#fff"
  });
  img.onload = () => {
    const canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;
    const ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);
    const dataURL = canvas.toDataURL("image/png");
    const a = document.createElement("a");
    const event = new MouseEvent("click");
    a.download = name;
    a.href = dataURL;
    a.dispatchEvent(event);
    a.remove();
  };
};
